Skip to content

Expose abandoned transaction product params in filters#459

Merged
yusuftor merged 5 commits intosuperwall:developfrom
SebastianSzturo:SebastianSzturo/abandoned-duration
Apr 28, 2026
Merged

Expose abandoned transaction product params in filters#459
yusuftor merged 5 commits intosuperwall:developfrom
SebastianSzturo:SebastianSzturo/abandoned-duration

Conversation

@SebastianSzturo
Copy link
Copy Markdown
Contributor

@SebastianSzturo SebastianSzturo commented Apr 9, 2026

Problem

When configuring a paywall trigger for transaction_abandon, the dashboard filter UI only exposes abandoned_product_id.

The SDK already includes richer abandoned product metadata in the internal $product_* parameter set, but those fields are not copied into the explicit event parameter payload that powers the filter picker. As a result, you cannot target different paywalls based on the abandoned product duration.

Intended use case

The goal is to show a different rescue paywall depending on which subscription duration was abandoned. For example:

  • If the user abandons a yearly product, show a discounted yearly paywall
  • If the user abandons a monthly product, show a discounted monthly paywall
  • If the user abandons a weekly product, show a discounted weekly paywall

Right now that workflow is blocked because transaction_abandon does not expose duration-related fields in the filter UI.

Solution

  • Copy available abandoned product attributes into explicit abandoned_product_* event parameters
  • Preserve the existing abandoned_product_id field
  • Avoid emitting misleading empty duration fields for blank products used by Stripe/web checkout fallback paths
  • Add test coverage for the new transaction_abandon parameter set

Notes

This addresses the App Store abandon path where a real StoreProduct is available. Stripe/web checkout abandon still only has product ID in the current model, so duration-based filtering for that path would require additional Stripe product metadata to be tracked.

Greptile Summary

This PR copies StoreProduct.attributes into the transaction_abandon audience filter params under an abandoned_product_* prefix, guarded by !product.period.isEmpty so that Stripe/web products (which return an empty period) are unaffected. The SKProductSubscriptionPeriodMock is updated from a hardcoded numberOfUnits: 1 to a configurable init to support the new test, following the same pattern already used by MockSkProduct.

Confidence Score: 5/5

This PR is safe to merge; the change is additive, well-guarded, and consistent with the existing product_* attribute pattern.

No P0 or P1 issues found. The !product.period.isEmpty guard correctly scopes the new params to App Store subscription products, the identifier key is explicitly excluded to avoid a duplicate with the separately set abandoned_product_id, and the implementation mirrors the pre-existing product_* pattern in PaywallInfo.audienceFilterParams(). Test coverage uses actual-value assertions for all new fields.

No files require special attention.

Important Files Changed

Filename Overview
Sources/SuperwallKit/Analytics/Internal Tracking/Trackable Events/TrackableSuperwallEvent.swift Adds abandoned_product_* params for subscription products in the transaction_abandon case, guarded by !product.period.isEmpty; excludes identifier key to avoid duplicate with abandoned_product_id.
Tests/SuperwallKitTests/Analytics/Internal Tracking/TrackTests.swift Adds a new transaction_abandon test with actual-value assertions for the new abandoned_product_* fields and confirms abandoned_product_identifier is nil.
Tests/SuperwallKitTests/StoreKit/Mocks/SKProductSubscriptionPeriodMock.swift Replaces hardcoded numberOfUnits: 1 with configurable init(numberOfUnits:unit:), matching the pattern used by MockSkProduct; existing callers retain the default behavior.
CHANGELOG.md Adds changelog entry for the new exposed abandoned product params in audience filters.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Transaction.abandon state] --> B{product != nil?}
    B -- No --> E[return audienceFilterParams]
    B -- Yes --> C["set abandoned_product_id"]
    C --> D{"product.period.isEmpty?"}
    D -- "Yes - Stripe/web product" --> E
    D -- "No - App Store subscription" --> F["iterate product.attributes\nexcluding 'identifier' key"]
    F --> G["add abandoned_product_period\nabandoned_product_period_months\nabandoned_product_price, etc."]
    G --> E
Loading

Reviews (3): Last reviewed commit: "Remove stray character in CHANGELOG" | Re-trigger Greptile

Comment thread Tests/SuperwallKitTests/Analytics/Internal Tracking/TrackTests.swift Outdated
@SebastianSzturo
Copy link
Copy Markdown
Contributor Author

@yusuftor @jakemor Lmk what you think!

@SebastianSzturo
Copy link
Copy Markdown
Contributor Author

Thanks @yusuftor ❤️

@yusuftor yusuftor merged commit d9e8548 into superwall:develop Apr 28, 2026
1 check passed
@yusuftor
Copy link
Copy Markdown
Collaborator

Thanks for submitting!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants